package com.terra.ns.imp.system.api

import cn.hutool.core.util.IdUtil
import cn.hutool.core.util.PhoneUtil
import cn.hutool.core.util.RandomUtil
import cn.hutool.json.JSONUtil
import com.terra.ns.imp.common.core.constant.GlobalErrorCode
import com.terra.ns.imp.common.redis.utils.RedisUtils
import com.terra.ns.imp.common.sms.SmsTemplate
import com.terra.ns.imp.common.sms.config.SmsProperties
import com.terra.ns.imp.system.api.service.ISmsCaptchaApi
import com.terra.ns.imp.system.api.vo.request.SmsCaptchaRequest
import com.terra.ns.imp.system.constant.SystemErrorCode
import com.terra.ns.imp.system.convert.SmsLogConvert
import com.terra.ns.imp.system.exception.SystemServiceException
import com.terra.ns.imp.system.mapper.StSmsTemplateMapper
import com.terra.ns.imp.system.service.IStSmsLogService
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
import java.time.Duration

/**
@author qins
@date 2023/6/7
@desc 短信验证API实现
 */
@Service
class SmsCaptchaApiImpl : ISmsCaptchaApi {

    @Autowired
    private lateinit var smsTemplate: SmsTemplate

    @Autowired
    private lateinit var smsProperties: SmsProperties

    @Autowired
    private lateinit var smsLogService: IStSmsLogService

    @Autowired
    private lateinit var smsTemplateMapper: StSmsTemplateMapper

    override fun getPhoneCaptcha(request: SmsCaptchaRequest): String {
        if(!PhoneUtil.isPhone(request.phone)) {
            throw SystemServiceException(SystemErrorCode.PHONE_FORMAT_ERROR)
        }
        val template = smsTemplateMapper.selectOneByType(request.templateType)
            ?: throw SystemServiceException(SystemErrorCode.SMS_TEMPLATE_NOT_EXIST)
        val templateCode = template.templateCode!!
        val templateContent = template.templateContent!!
        val code = RandomUtil.randomNumbers(6)
        val uuid = IdUtil.fastSimpleUUID()
        val param = mapOf(Pair("code", code))
        try {
            smsTemplate.send(request.phone, templateCode, param)
            RedisUtils.set(getSmsCaptchaKey(uuid, request.phone, request.templateType), code, Duration.ofSeconds(smsProperties.expireTime))
            smsLogService.syncSaveLog(SmsLogConvert.convert(uuid, request.phone, templateCode, templateContent, JSONUtil.toJsonStr(param), GlobalErrorCode.SUCCESS.code, "发送成功"))
        } catch (e: Exception) {
            val ex = SystemServiceException(SystemErrorCode.CAPTCHA_CREATE_ERROR, e.message ?: "")
            smsLogService.syncSaveLog(SmsLogConvert.convert(uuid, request.phone, templateCode, templateContent, JSONUtil.toJsonStr(param), ex.code, ex.message))
            throw ex
        }
        return uuid
    }

    override fun verifySmsCaptcha(uuid: String?, phone: String?, type: Int?, code: String?): Boolean {
        if(uuid.isNullOrBlank()) {
            return code.isNullOrBlank()
        }
        val key = getSmsCaptchaKey(uuid, phone ?: "", type ?: 0)
        if (!RedisUtils.hasKey(key) || RedisUtils.get<String>(key) != code) {
            return false
        }
        RedisUtils.delete(key)
        return true
    }

    private fun getSmsCaptchaKey(uuid: String, phone: String, type: Int) = "sms:$uuid:$phone:$type"
}